home *** CD-ROM | disk | FTP | other *** search
- /* {{{ Copyright notice */
-
- /* View file module for the Midnight Commander
- Copyright (C) 1994, 1995 The Free Software Foundation
- Written by: 1994, 1995 Miguel de Icaza
- 1994, 1995 Janne Kukonlehto
- 1995 Jakub Jelinek
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* }}} */
- /* {{{ Declarations */
- #include <config.h>
- #include <stdio.h>
- #include <sys/types.h>
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #include <string.h>
- #include "tty.h"
- #include <sys/stat.h>
- #ifdef HAVE_MMAP
- # include <sys/mman.h>
- #endif
- #include <fcntl.h>
- #include <unistd.h>
- #include <ctype.h> /* For toupper() */
- #include <stdlib.h> /* atoi() */
- #include <malloc.h>
- #include <errno.h>
- #include <limits.h>
- #include <sys/param.h>
-
- #include "mem.h"
- #include "mad.h"
- #include "util.h"
- #include "dlg.h" /* Needed by widget.h */
- #include "widget.h" /* Needed for buttonbar_new */
- #include "color.h"
- #include "dialog.h"
- #include "file.h"
- #include "mouse.h"
- #include "global.h"
- #include "help.h"
- #include "key.h" /* For mi_getch() */
- #include "layout.h"
- #if defined(HAVE_RX_H) && defined(HAVE_REGCOMP)
- #include <rx.h>
- #else
- #include "regex.h"
- #endif
- #include "fs.h"
- #include "../vfs/vfs.h"
- #include "dir.h"
- #include "panel.h" /* Needed for current_panel and other_panel */
- #include "win.h"
- #include "main.h" /* For the externs */
- #define WANT_WIDGETS
- #include "view.h"
-
- #ifndef MAP_FILE
- #define MAP_FILE 0
- #endif
-
- /* Block size for reading files in parts */
- #define READ_BLOCK 8192
- #define VIEW_PAGE_SIZE 8192
-
- #ifdef IS_AIX
- # define IFAIX(x) case (x):
- #else
- # define IFAIX(x)
- #endif
-
- /* Maxlimit for skipping updates */
- int max_dirt_limit =
- #ifdef _OS_NT
- 0;
- #else
- 10;
- #endif
-
- /* Our callback */
- static int view_callback (Dlg_head *h, WView *view, int msg, int par);
-
- /* Wrap mode */
- int wrap_mode = 1;
-
- /* Scrolling is done in pages or line increments */
- int mouse_move_pages_viewer = 1;
-
- /* Used to compute the bottom first variable */
- int have_fast_cpu = 0;
-
- int default_hex_mode = 0;
- int default_magic_flag = 1;
- int default_nroff_flag = 0;
- int altered_hex_mode = 0;
- int altered_magic_flag = 0;
- int altered_nroff_flag = 0;
- /* }}} */
-
- /* "$Id: view.c,v 1.19 1995/02/21 19:07:38 miguel Exp $" */
-
- static char hex_char[] = "0123456789ABCDEF";
-
- /* }}} */
- /* {{{ Clean-up functions */
-
- void free_file (WView *view)
- {
- int i;
-
- #ifdef HAVE_MMAP
-
- if (view->mmaping){
- mc_munmap (view->data, view->s.st_size);
- mc_close (view->file);
- } else
- #endif /* HAVE_MMAP */
- {
- if (view->reading_pipe){
- /* Check error messages */
- if (!view->have_frame)
- check_error_pipe ();
-
- /* Close pipe */
- pclose (view->stdfile);
-
- /* Ignore errors because we don't want to hear about broken pipe */
- close_error_pipe (-1, NULL);
- } else {
- if (view->file != -1)
- mc_close (view->file);
- }
- }
- /* Block_ptr may be zero if the file was a file with 0 bytes */
- if (view->growing_buffer && view->block_ptr){
- for (i = 0; i < view->blocks; i++){
- free (view->block_ptr [i].data);
- }
- free (view->block_ptr);
- }
- }
-
- /* Both views */
- void view_done (WView *view)
- {
- if (view->view_active){
- free_file (view);
- free (view->filename);
- if (view->command)
- free (view->command);
- }
- view->view_active = 0;
- default_hex_mode = view->hex_mode;
- default_nroff_flag = view->viewer_nroff_flag;
- default_magic_flag = view->viewer_magic_flag;
- }
-
- static void view_hook (void *);
-
- void view_destroy (WView *view)
- {
- view_done (view);
- if (view->have_frame)
- delete_hook (&select_file_hook, view_hook);
- #ifdef HAVE_TK
- free (view->cache);
- free (view->color_cache);
- #endif
- }
-
- static int get_byte (WView *view, int byte_index)
- {
- int page = byte_index / VIEW_PAGE_SIZE + 1;
- int offset = byte_index % VIEW_PAGE_SIZE;
- int i, n;
- block_ptr_t *tmp;
-
- if (view->growing_buffer){
- if (page > view->blocks){
- tmp = xmalloc (sizeof (block_ptr_t) * page, "get_byte");
- if (view->block_ptr){
- bcopy (view->block_ptr, tmp, sizeof (block_ptr_t) *
- view->blocks);
- free (view->block_ptr);
- }
- view->block_ptr = tmp;
- for (i = view->blocks; i < page; i++){
- char *p = malloc (VIEW_PAGE_SIZE);
- view->block_ptr [i].data = p;
- if (!p)
- return '\n';
- if (view->stdfile != (FILE *)-1)
- n = fread (p, 1, VIEW_PAGE_SIZE, view->stdfile);
- else
- n = mc_read (view->file, p, VIEW_PAGE_SIZE);
- if (n != -1)
- view->bytes_read += n;
- if (view->s.st_size < view->bytes_read){
- view->bottom_first = -1; /* Invalidate cache */
- view->s.st_size = view->bytes_read;
- view->last_byte = view->bytes_read;
- if (view->reading_pipe)
- view->last_byte = view->first + view->bytes_read;
- }
- /* To force loading the next page */
- if (n == VIEW_PAGE_SIZE && view->reading_pipe){
- view->last_byte++;
- }
- }
- view->blocks = page;
- }
- if (byte_index > view->bytes_read){
- return -1;
- } else
- return view->block_ptr [page-1].data [offset];
- } else {
- if (byte_index >= view->last_byte)
- return -1;
- else
- return view->data [byte_index];
- }
- }
-
- static char *set_view_init_error (WView *view, char *msg)
- {
- view->growing_buffer = 0;
- view->reading_pipe = 0;
- view->first = 0;
- if (msg){
- view->bytes_read = strlen (msg);
- return strdup (msg);
- }
- return 0;
- }
-
- /* return values: 0 for success, else points to error message */
- static char *init_growing_view (WView *view, char *name, char *filename)
- {
- view->growing_buffer = 1;
-
- if (name){
- view->reading_pipe = 1;
- view->s.st_size = 0;
-
- open_error_pipe ();
- if ((view->stdfile = popen (name, "r")) == NULL){
- close_error_pipe (view->have_frame?-1:1, view->data);
- return set_view_init_error (view, " Can't spawn child program ");
- }
-
- #ifndef HAVE_XVIEW
- /* First, check if filter produced any output */
- get_byte (view, 0);
- if (view->bytes_read <= 0){
- pclose (view->stdfile);
- close_error_pipe (view->have_frame?-1:1, view->data);
- return set_view_init_error (view, " Empty output from child filter ");
- }
- #endif
- } else {
- view->stdfile = (FILE *)-1;
- if ((view->file = mc_open (filename, O_RDONLY)) == -1)
- return set_view_init_error (view, " Could not open file ");
- }
- return 0;
- }
-
- /* Load filename into core */
- /* returns:
- -1 on failure.
- if (have_frame), we return success, but data points to a
- error message instead of the file buffer (quick_view feature).
- */
- static char *load_view_file (WView *view, char *filename)
- {
- char *cmd;
-
- #ifndef HAVE_MMAP
- int count;
- #endif
-
- if ((view->file = mc_open (filename, O_RDONLY)) < 0){
- set_view_init_error (view, 0);
- return (copy_strings (" Can't open file \"",
- filename, "\"\n ",
- unix_error_string (errno), " ", 0));
-
- }
- if (mc_fstat (view->file, &view->s) < 0){
- set_view_init_error (view, 0);
- mc_close (view->file);
- return copy_strings (" Can't stat file \n ",
- unix_error_string (errno), " ", 0);
- }
- if (S_ISDIR (view->s.st_mode) || S_ISSOCK (view->s.st_mode)
- || S_ISFIFO (view->s.st_mode)){
- mc_close (view->file);
- return set_view_init_error (view, " Can't view: not a regular file ");
- }
-
- #ifdef JUST_FOR_CULTURAL_INFORMATION
- /* #ifed out because now we have growing buffers :-) */
- if (view->s.st_size < 1) {
- mc_close (view->file);
- return set_view_init_error (view, " Can't view empty file ");
- }
- #endif
- if (view->s.st_size == 0){
- /* Must be one of those nice files that grow (/proc) */
- mc_close (view->file);
- return init_growing_view (view, 0, filename);
- }
-
- /* First, try to open a compressed file */
- if (!view->viewer_magic_flag && (is_gunzipable (view->file)) != 0){
- mc_close (view->file);
- cmd = copy_strings ("gzip -dc ", "'", filename, "'", 0);
- return init_growing_view (view, cmd, filename);
- }
-
- /* Otherwise, the file wasn't compressed */
- #ifdef HAVE_MMAP
- view->data = mc_mmap (0, view->s.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
- view->file, 0);
- if ((caddr_t) view->data == (caddr_t) -1){
- mc_close (view->file);
- /* set_view_init_error (view, 0);
- return copy_strings (" Can't mmap file \n ",
- unix_error_string (errno), " ", 0);*/
- return init_growing_view (view, 0, filename);
-
- }
- view->first = 0;
- view->bytes_read = view->s.st_size;
- view->mmaping = 1;
- return 0;
- #else
- mc_close (view->file);
- return init_growing_view (view, 0, filename);
- #endif
- }
-
- /* Return zero on success, -1 on failure */
- int do_view_init (WView *view, char *_command, char *_file)
- {
- char *error = 0;
- int i;
-
- if (view->view_active)
- view_done (view);
-
- /* Set up the state */
- view->block_ptr = 0;
- view->data = NULL;
- view->growing_buffer = 0;
- view->reading_pipe = 0;
- view->mmaping = 0;
- view->blocks = 0;
- view->block_ptr = 0;
- view->first = view->bytes_read = 0;
-
- /* Clear the markers */
- view->marker = 0;
- for (i = 0; i < 10; i++)
- view->marks [i] = 0;
-
-
- if (!view->have_frame){
- /* hex_mode = 0; */
- /* wrap_mode = 1; */
- view->start_col = 0;
- }
- if (_command && view->viewer_magic_flag)
- error = init_growing_view (view, _command, _file);
- else
- error = load_view_file (view, _file);
-
- if (error){
- if (!view->have_frame){
- message (1, " Error ", error);
- free (error);
- return -1;
- }
- }
-
- view->view_active = 1;
- view->filename = strdup (_file);
- if (_command)
- view->command = strdup (_command);
- else
- view->command = 0;
- view->search_start = view->start_display = view->first;
- view->found_len = 0;
- view->start_col = 0;
- view->last_search = 0; /* Start a new search */
-
- /* Special case: The data points to the error message */
- if (error){
- view->data = error;
- view->s.st_size = view->bytes_read = strlen (view->data);
- }
- view->last_byte = view->first + view->s.st_size;
-
- return 0;
- }
-
-
- /* Both views */
- /* Return zero on success, -1 on failure */
- int view_init (WView *view, char *_command, char *_file)
- {
- int cols;
-
- if (view->have_frame)
- cols = view->widget.cols - 2;
- else
- cols = view->widget.cols;
-
- view->bottom_first = -1;
- view->bytes_per_line = 2 * (cols - 7) / 9;
- view->bytes_per_line &= 0xfffc;
- view->dirty = max_dirt_limit + 1; /* To force refresh */
- if (!view->view_active || strcmp (_file, view->filename))
- return do_view_init (view, _command, _file);
- else
- return 0;
- }
-
- /* }}} */
-
- /* {{{ X Window code */
- #ifdef HAVE_TK
- #include "tkmain.h"
-
- /* Accepts the dim command with the width and the height in characters */
- static int
- tk_viewer_callback (ClientData cd, Tcl_Interp *interp, int ac, char *av[])
- {
- WView *view = (WView *) cd;
-
- if (av [1][0] != 'd')
- return TCL_OK;
- view->widget.cols = atoi (av [2]);
- view->widget.lines = atoi (av [3]);
- return TCL_OK;
- }
-
- void x_create_viewer (WView *view)
- {
- char *cmd;
- char *parent;
-
- /* First, check if our parent is ".", if this is the case, then
- * create a stand alone viewer, otherwise, we create a paneled
- * version of the viewer
- */
-
- if (view->have_frame){
- parent = view->widget.wcontainer;
- } else {
- parent = view->widget.parent->wdata;
- }
- cmd = tk_new_command (parent, view, tk_viewer_callback, 'v');
-
- tk_evalf ("newview %d %s %s %s", view->have_frame,
- view->have_frame ? (char *) view->widget.wcontainer : "{}",
- cmd+1, cmd);
- }
- #else
- # define x_create_viewer(x)
- #endif
- /* }}} */
-
- /* {{{ Screen update functions */
-
- #ifdef HAVE_TK
- static void view_status (WView *view)
- {
- char *window = wtk_win (view->widget);
-
- if (!view->status_shown){
- view->status_shown = 0;
-
- tk_evalf ("view_update_info %s {%s} {%d} {%s} {%s}",
- window, name_trunc (view->filename ? view->filename:
- view->command ? view->command:"", 20),
- -view->start_col, size_trunc (view->s.st_size),
- view->growing_buffer ? "[grow]":"[]");
- }
- }
-
- static void view_percent (WView *view, int p, int w)
- {
- fprintf (stderr, "Missing tk view_percent\n");
- }
- #else
- static void view_percent (WView *view, int p, int w)
- {
- int percent;
-
- percent = view->s.st_size == 0 ? 100 :
- (view->last_byte == view->last ? 100 :
- (p)*100 / view->s.st_size);
-
- widget_move (view, view->have_frame, w - 5);
- printw ("%3d%% ", percent);
- }
-
- static void view_status (WView *view)
- {
- int w = view->widget.cols - (view->have_frame * 2);
- int i;
-
- attrset (SELECTED_COLOR);
- widget_move (view, view->have_frame, view->have_frame);
- hline (' ', w);
- if (w > 6){
- i = w > 24 ? 18 : w - 6;
- printw ("File: %s", name_trunc (view->filename ? view->filename:
- view->command ? view->command:"", i));
- if (w > 30){
- widget_move (view, view->have_frame, 26);
- printw ("Col %d", -view->start_col);
- }
- if (w > 60){
- widget_move (view, view->have_frame, 42);
- printw ("%s bytes", size_trunc (view->s.st_size));
- }
- if (w > 70){
- printw (" ");
- if (view->growing_buffer)
- addstr (" [grow]");
- }
- if (w - i > 4)
- view_percent (view, view->start_display-view->first, w);
- }
- attrset (SELECTED_COLOR);
- }
- #endif
-
- #ifdef HAVE_TK
-
- #define DEF_COLOR 0
- #define BOLD_COLOR 1
- #define UNDERLINE_COLOR 2
- #define MARK_COLOR 3
-
- /* The major part of the Tk code deals with caching a line (the
- * current one) of text to avoid expensive calls to the Tk text widget
- * callback.
- *
- * We cache all this information on view->cache and the colors on
- * view->color_cache.
- *
- * FIXME: the cache does not know about the contents of the physical
- * text widget (depends on your concept of physical), so if we happen
- * to hit the case where row is decremented in the void display () routine,
- * we will end up with a clean line.
- */
-
- static int current_color;
-
- static void set_color (int font)
- {
- current_color = font;
- }
-
- static inline void display_clean(WView *view, int h, int w)
- {
- char *win = wtk_win (view->widget);
-
- tk_evalf ("cleanview %s.v.view", win);
- }
-
- static void add_character (WView *view, int c)
- {
- view->cache [view->dest] = c;
- view->color_cache [view->dest] = current_color;
- }
-
- static inline void add_string (WView *view, char *s)
- {
- while (*s)
- add_character (view, *s++);
- }
-
- static char *get_tk_tag_name (int color)
- {
- /* Those names are the names of the tags in the Tk source */
- static char *color_tag_names [] = {
- "normal", "bold", "underline", "mark"
- };
-
- return color_tag_names [color];
- }
-
- /*
- * Tk: Flushes the contents of view->cache to the Tk text widget
- *
- * We get the command information and call the command directly
- * to avoid escaping the view->cache contents.
- */
- static void flush_line (WView *view)
- {
- char *win = wtk_win (view->widget);
- int row = view->current_line;
- char *text_name;
- Tcl_CmdInfo info;
- int i, prev_color;
- char str_row [30];
- char *av [5];
- int len = strlen (view->cache);
-
- /* Fetch the address and clientData for the view */
- text_name = copy_strings (win, ".v.view", 0);
- Tcl_GetCommandInfo (interp, text_name, &info);
-
- /* Setup arguments to the command:
- * $win.v.view insert @$row,0 $view->cache
- */
- sprintf (str_row, "%d.0", row);
- i = 0;
- av [i++] = text_name;
- av [i++] = "insert";
- av [i++] = str_row;
- av [i++] = view->cache;
-
- /* Call the callback :-) */
- (*info.proc) (info.clientData, interp, i, av);
- bzero (view->cache, view->cache_len);
-
- /* Colorize the line */
- for (prev_color = 0, i = 0; i < len; i++){
- int new_color_start;
- char *color_name;
-
- if (view->color_cache [i] == prev_color)
- continue;
-
- new_color_start = i;
-
- prev_color = view->color_cache [i];
-
- for (;i < len && view->color_cache [i] == prev_color; i++)
- ;
-
- color_name = get_tk_tag_name (prev_color);
- tk_evalf ("%s tag add %s %d.%d %d.%d",
- text_name, color_name,
- row, new_color_start-1,
- row, i);
- }
-
- bzero (view->color_cache, view->cache_len);
- view->last_col = 0;
- free (text_name);
- }
-
- /* Tk: Mantains the line cache */
- void view_gotoyx (WView *view, int row, int col)
- {
- if (row != view->current_line){
- fprintf (stderr, "%d\n", row);
- flush_line (view);
- }
- view->current_line = row;
-
- /* In case the user has resized the viewer */
- if (col > view->cache_len){
- char *new;
-
- new = xmalloc (col + 1, "cache");
- strcpy (new, view->cache);
- free (view->cache);
- view->cache = new;
-
- new = xmalloc (col + 1, "cache");
- strcpy (new, view->color_cache);
- free (view->color_cache);
- view->color_cache = new;
-
- view->cache_len = col;
- }
-
- view->dest = col;
- for (; view->last_col+1 < col; view->last_col++){
- view->cache [view->last_col] = ' ';
- view->color_cache [view->last_col] = current_color;
- }
- view->last_col = col;
- }
-
- #else
-
- #define BOLD_COLOR MARKED_COLOR
- #define UNDERLINE_COLOR VIEW_UNDERLINED_COLOR
- #define MARK_COLOR SELECTED_COLOR
- #define DEF_COLOR NORMAL_COLOR
-
- #define set_color(font) attrset (font)
-
-
- static inline void display_clean (WView *view, int height, int width)
- {
- /* FIXME: Should I use widget_erase only and repaint the box? */
- if (view->have_frame){
- int i;
-
- draw_double_box (view->widget.parent, view->widget.y, view->widget.x,
- view->widget.lines, view->widget.cols);
- for (i = 1; i < height; i++){
- widget_move (view, i, 1);
- printw ("%*s", width-1, "");
- }
- } else
- widget_erase ((Widget *) view);
- }
-
- #define add_character(view,c) addch (c)
- #define add_string(view,s) addstr (s)
- #define view_gotoyx(v,r,c) widget_move (v,r,c)
-
- #endif
-
- /* Shows the file pointed to by *start_display on view_win */
- static long display (WView *view)
- {
- #ifdef HAVE_X
- # define frame_shift 0
- #else
- const int frame_shift = view->have_frame;
- #endif
- int col = 0 + frame_shift;
- int row = 1 + frame_shift;
- int height, width;
- long from;
- int c;
- int boldflag = 0;
-
- height = view->widget.lines - frame_shift;
- width = view->widget.cols - frame_shift;
- from = view->start_display;
- set_color (DEF_COLOR);
-
- display_clean (view, height, width);
-
- if (view->hex_mode){
- char hex_buff[10]; /* A temporary buffer for sprintf and mvwaddstr */
- int bytes; /* Number of bytes already printed on the line */
- /* Start of text column */
- int text_start = width - view->bytes_per_line - 1 + frame_shift;
-
- for (;row < height && from < view->last_byte; row++){
- /* Print the hex offset */
- sprintf (hex_buff, "%05X", (int) (from - view->first));
- widget_move (view, row, frame_shift);
- add_string (view, hex_buff);
-
- /* Hex dump starts from column seven */
- col = 7;
-
- /* Each hex number is two digits */
- hex_buff[2] = 0;
- for (bytes = 0; bytes < view->bytes_per_line
- && from < view->last_byte; bytes++, from++){
- c = (unsigned char) get_byte (view, from);
-
- if (view->found_len && from >= view->search_start
- && from < view->search_start + view->found_len){
- boldflag = 1;
- set_color (BOLD_COLOR);
- }
-
- /* Print a hex number (sprintf is too slow) */
- hex_buff [0] = hex_char [(c >> 4)];
- hex_buff [1] = hex_char [c & 15];
- view_gotoyx (view, row, col);
- add_string (view, hex_buff);
- col += 3;
- if ((bytes & 3) == 3 && bytes + 1 < view->bytes_per_line){
-
- if (boldflag && from == view->search_start + view->found_len - 1)
- set_color (DEF_COLOR);
-
- /* Hex numbers are printed in the groups of four */
- /* Groups are separated by a vline */
-
- add_character (view, ' ');
- one_vline ();
- view_gotoyx (view, row, col + 1);
- col += 2;
-
- if (boldflag && from==view->search_start+view->found_len-1)
- set_color (BOLD_COLOR);
-
- }
- if (boldflag && from < view->search_start + view->found_len - 1
- && bytes != view->bytes_per_line - 1)
- add_character (view, ' ');
-
- /* Print the corresponding ascii character */
- view_gotoyx (view, row, text_start + bytes);
-
- if (!is_printable (c))
- c = '.';
- add_character (view, c);
-
- if (boldflag){
- boldflag = 0;
- set_color (DEF_COLOR);
- }
- }
- }
- } else {
- if (view->growing_buffer && from == view->last_byte)
- get_byte (view, from);
- for (; row < height && from < view->last_byte; from++){
- c = get_byte (view, from);
- if ((c == '\n') || (col == width && wrap_mode)){
- col = frame_shift;
- row++;
- if (c == '\n' || row >= height)
- continue;
- }
- if (c == '\r')
- continue;
- if (c == '\t'){
- col = ((col - frame_shift)/8)*8 + 8 + frame_shift;
- continue;
- }
- if (view->viewer_nroff_flag && c == '\b'){
- if (from + 1 < view->last_byte
- && is_printable (get_byte (view, from + 1)) &&
- from > view->first
- && is_printable (get_byte (view, from - 1)))
- {
- if (col <= frame_shift){
- /* So it has to be wrap_mode - do not need to check for it */
- if (row == 1 + frame_shift){
- from++;
- continue; /* There had to be a bold character on the rightmost position
- of the previous undisplayed line */
- }
- row--;
- col = width;
- }
- col--;
- boldflag = 1;
- if (get_byte (view, from - 1) == '_' && get_byte (view, from + 1) != '_')
- set_color (UNDERLINE_COLOR);
- else
- set_color (BOLD_COLOR);
- continue;
- }
- }
- if (view->found_len && from >= view->search_start
- && from < view->search_start + view->found_len){
- boldflag = 1;
- set_color (MARK_COLOR);
- }
- if (col >= frame_shift-view->start_col
- && col < width-view->start_col)
- {
- view_gotoyx (view, row, col+view->start_col);
- if (!is_printable (c))
- c = '.';
-
- add_character (view, c);
- }
- col++;
- if (boldflag){
- boldflag = 0;
- set_color (DEF_COLOR);
- }
- }
- #ifdef HAVE_TK
- /* Tk: This flushes the last line */
- view_gotoyx (view, view->current_line+1, 0);
- #endif
-
- if (view->growing_buffer && from == view->last_byte)
- get_byte (view, from);
- }
- view->last = from;
- return from;
- }
-
- void view_update (WView *view)
- {
- static int dirt_limit = 1;
-
- if (view->dirty > dirt_limit){
- /* Too many updates skipped -> force a update */
- display (view);
- view_status (view);
- view->dirty = 0;
- /* Raise the update skipping limit */
- dirt_limit++;
- if (dirt_limit > max_dirt_limit)
- dirt_limit = max_dirt_limit;
- }
- if (view->dirty){
- if (is_idle ()){
- /* We have time to update the screen properly */
- display (view);
- view_status (view);
- view->dirty = 0;
- if (dirt_limit > 1)
- dirt_limit--;
- } else {
- /* We are busy -> skipping full update,
- only the status line is updated */
- view_status (view);
- }
- /* Here we had a refresh, if fast scrolling does not work
- restore the refresh, althought this should not happend */
- }
- }
-
- static inline void my_define (Dlg_head *h, int idx, char *text,
- void (*fn)(WView *), WView *view)
- {
- define_label_data (h, (Widget *) view, idx, text, (buttonbarfn) fn, view);
- }
-
- /* }}} */
- /* {{{ Movement functions */
- /* If the last parameter is nonzero, it means we want get the count of lines
- from current up to the the upto position inclusive */
- static long move_forward2 (WView *view, long current, int lines, long upto)
- {
- long p, q;
- int line;
- int col = 0;
-
- if (!upto && view->last == view->last_byte)
- return current;
-
- if (view->hex_mode){
- return (p = current + lines * view->bytes_per_line) >= view->last_byte ? current : p;
- } else {
- if (upto){
- lines = -1;
- q = upto;
- } else
- q = view->last_byte;
- for (line = col = 0, p = current; p < q; p++){
- int c;
-
- if (lines != -1 && line >= lines)
- return p;
-
- c = get_byte (view, p);
-
- if (wrap_mode){
- if (c == '\r')
- continue; /* This characters is never displayed */
- else if (c == '\t')
- col = ((col - view->have_frame)/8)*8 +8+ view->have_frame;
- else
- col++;
- if (view->viewer_nroff_flag && c == '\b'){
- if (p + 1 < view->last_byte
- && is_printable (get_byte (view, p + 1))
- && p > view->first
- && is_printable (get_byte (view, p - 1)))
- col -= 2;
- } else if (col == vwidth){
- /* FIXME: the c in is_printable was a p, that is a bug,
- I suspect I got that fix from Jakub, same applies
- for d. */
- int d = get_byte (view, p+2);
-
- if (p + 2 >= view->last_byte || !is_printable (c) ||
- !view->viewer_nroff_flag || get_byte (view, p + 1) != '\b' ||
- !is_printable (d)){
- col = 0;
-
- if (c == '\n' || get_byte (view, p+1) != '\n')
- line++;
- }
- } else if (c == '\n'){
- line++;
- col = 0;
- }
- } else if (c == '\n')
- line++;
- }
- if (upto)
- return line;
- }
- return current;
- }
-
- /* returns the new current pointer */
- /* Cause even the forward routine became very complex, we in the wrap_mode
- just find the nearest '\n', use move_forward2(p, 0, q) to get the count
- of lines up to there and then use move_forward2(p, something, 0), which we
- return */
- static long move_backward2 (WView *view, long current, int lines)
- {
- long p, q;
- int line;
-
- if (current == view->first)
- return current;
-
- if (view->hex_mode){
- p = current - lines * view->bytes_per_line;
-
- return (p < view->first) ? view->first : p;
- } else {
- if (current == view->last_byte
- && get_byte (view, current - 1) != '\n')
- /* There is one virtual '\n' at the end,
- so that the last line is shown */
- line = 1;
- else
- line = 0;
- for (q = p = current - 1; p > view->first; p--)
- if (get_byte (view, p) == '\n')
- if (!wrap_mode){
- if (line == lines)
- return p + 1;
- line++;
- } else {
- line += move_forward2 (view, p + 1, 0, q);
- if (line >= lines){
- if (line == lines)
- return p + 1;
- else
- return move_forward2 (view, p + 1, line - lines, 0);
- }
- q = p + 1;
- }
- }
- return p;
- }
-
- static void move_backward (WView *view, int i)
- {
- view->search_start = view->start_display =
- move_backward2 (view, view->start_display, i);
- view->found_len = 0;
- view->dirty++;
- }
-
- static long get_bottom_first (WView *view, int do_not_cache, int really)
- {
- int bottom_first;
-
- if (!have_fast_cpu && !really)
- return INT_MAX;
-
- if (!do_not_cache && view->bottom_first != -1)
- return view->bottom_first;
-
- /* Force loading */
- if (view->growing_buffer){
- int old_last_byte;
-
- old_last_byte = -1;
- while (old_last_byte != view->last_byte){
- old_last_byte = view->last_byte;
- get_byte (view, view->last_byte+VIEW_PAGE_SIZE);
- }
- }
-
- bottom_first = move_backward2 (view, view->last_byte, vheight - 1);
-
- if (view->hex_mode)
- bottom_first = (bottom_first + view->bytes_per_line - 1)
- / view->bytes_per_line * view->bytes_per_line;
- view->bottom_first = bottom_first;
-
- return view->bottom_first;
- }
-
- static void move_forward (WView *view, int i)
- {
- view->start_display = move_forward2 (view, view->start_display, i, 0);
- if (!view->reading_pipe && view->start_display > get_bottom_first (view, 0, 0))
- view->start_display = view->bottom_first;
- view->search_start = view->start_display;
- view->found_len = 0;
- view->dirty++;
- }
-
-
- static void move_to_top (WView *view)
- {
- view->search_start = view->start_display = view->first;
- view->found_len = 0;
- view->dirty++;
- }
-
- static void move_to_bottom (WView *view)
- {
- view->search_start = view->start_display = get_bottom_first (view, 0, 1);
- view->found_len = 0;
- view->dirty++;
- }
-
- /* Scroll left/right the view panel functions */
- static void move_right (WView *view)
- {
- if (wrap_mode)
- return;
-
- if (--view->start_col > 0)
- view->start_col = 0;
- view->dirty++;
- }
-
- static void move_left (WView *view)
- {
- if (wrap_mode)
- return;
-
- if (++view->start_col > 0)
- view->start_col = 0;
- view->dirty++;
- }
-
- /* }}} */
- /* {{{ Search routines */
-
- /* Case insensitive search of text in data */
- static int icase_search_p (WView *view, char *text, char *data, int nothing)
- {
- int p = 0;
- char *q;
-
- p = (q = icase_search (text, data)) != 0;
- if (p){
- view->found_len = strlen (text);
- view->search_start = q - data - view->found_len;
- }
- return p;
- }
-
- static char *grow_string_buffer (char *text, int *size)
- {
- char *new;
- int old_size = *size;
-
- /* The grow steps */
- *size += 160;
- new = xmalloc (*size, "grow_string_buffer");
- strncpy (new, text, old_size);
- if (text)
- free (text);
- return new;
- }
-
- static char *get_line_at (WView *view, long *p)
- {
- char *buffer = 0;
- int buffer_size, usable_size;
- int ch;
- int direction;
- long pos = *p;
- long i;
-
- direction = view->direction;
- buffer_size = usable_size = 0;
-
- i = ch = 0;
- for (;pos >= 0 && (ch = get_byte (view, pos))!= -1; pos += direction, i++){
-
- /* skip over all the possible zeros in the file */
- if (ch == 0 && i == 0){
- while (pos >= 0 && ((ch = get_byte (view, pos)) != -1) && ch == 0)
- pos+= direction;
- if (ch == -1)
- break;
- }
- if (i == usable_size){
- buffer = grow_string_buffer (buffer, &buffer_size);
- usable_size = buffer_size - 2;
- buffer [0] = ' '; /* This makes possible strcpy of buffer */
- }
- buffer [i+1] = ch;
- if (ch == '\n' || !ch || ch == -1){
- pos += direction; i++;
- break;
- }
- }
- if (buffer){
- i--;
- buffer [0] = ' ';
- buffer [i+1] = 0;
-
- /* If we are searching backwards, reverse the string */
- if (view->direction < 0)
- reverse_string (buffer);
- }
-
- *p = pos;
- return buffer;
- }
-
- /** Search status optmizations **/
-
- /* The number of bytes between percent increments */
- int update_steps;
-
- /* Last point where we updated the status */
- long update_activate;
-
- static void search_update_steps (WView *view)
- {
- if (view->s.st_size)
- update_steps = 40000;
- else
- update_steps = view->last_byte / 100;
-
- /* Do not update the percent display but every 20 ks */
- if (update_steps < 20000)
- update_steps = 20000;
- }
-
- static void search (WView *view, char *text,
- int (*search)(WView *, char *, char *, int))
- {
- int w = view->widget.cols - (view->have_frame * 2);
- char *s = NULL; /* The line we read from the view buffer */
- long p, beginning;
- int ch;
- int isatbeg; /* Nonzero means we start search at beginning of some line */
- int found_len, search_start;
- Dlg_head *d = 0;
- int search_status;
-
- /* Used to keep track of where the line starts, when looking forward */
- /* is the index before transfering the line; the reverse case uses */
- /* the position returned after the line has been read */
- long forward_line_start;
- long reverse_line_start;
- long t;
- /* Clear interrupt status */
- got_interrupt ();
-
- if (verbose){
- d = message (D_INSERT, " Search ", "Searching %s", text);
- refresh ();
- }
- ch = 0;
- if (view->direction == 1){
- p = view->found_len ? view->search_start + 1 : view->search_start;
- } else {
- p = (view->found_len ? view->search_start : view->last) - 1;
- }
- beginning = p;
-
- isatbeg = view->found_len == 0;
- found_len = view->found_len;
- search_start = view->search_start;
-
- /* Compute the percent steps */
- search_update_steps (view);
- update_activate = 0;
-
- for (; ; isatbeg = 1, free (s)){
- #ifdef HAVE_TK
- static int count;
-
- if ((count++ % 32) == 0)
- tk_dispatch_all ();
- if (!d->running)
- break;
- #endif
- if (p >= update_activate){
- update_activate += update_steps;
- if (verbose){
- view_percent (view, p, w);
- refresh ();
- }
- if (got_interrupt ())
- break;
- }
- forward_line_start = p;
- disable_interrupt_key ();
- s = get_line_at (view, &p);
- reverse_line_start = p;
- enable_interrupt_key ();
- if (!s)
- break;
-
- search_status = (*search) (view, text, s + 1, match_normal);
- if (search_status < 0)
- break;
-
- if (search_status == 0)
- continue;
-
- /* We found the string */
-
- if (!isatbeg && !view->search_start){
-
- /* We do not want to match a
- * ^ regexp when not at the real
- * beginning of some line
- */
- view->found_len = found_len;
- view->search_start = search_start;
- if ((*search) (view, text, s, match_normal) <= 0)
- continue;
- (*search) (view, text, s + 1, match_normal);
- }
- /* Record the position used to continue the search */
- if (view->direction == 1)
- t = forward_line_start;
- else
- t = reverse_line_start ? reverse_line_start + 3 : 0;
- view->search_start += t;
-
- if (t != beginning){
- if (t > get_bottom_first (view, 0, 0))
- view->start_display = view->bottom_first;
- else
- view->start_display = t;
- }
-
- free (s);
- break;
- }
- disable_interrupt_key ();
- if (verbose){
- dlg_run_done (d);
- destroy_dlg (d);
- }
-
- if (!s){
- message (0, " Search ", " Search string not found ");
- view->found_len = 0;
- }
- }
-
- /* Search buffer (it's size is len) in the complete buffer */
- /* returns the position where the block was found */
- static long block_search (WView *view, char *buffer, int len)
- {
- int w = view->widget.cols - (view->have_frame * 2);
- char *d = buffer;
- long e;
-
- /* clear interrupt status */
- got_interrupt ();
- e = view->found_len ? view->search_start + 1 : view->search_start;
-
- search_update_steps (view);
- update_activate = 0;
-
- for (; e < view->last_byte; e++){
- if (e >= update_activate){
- update_activate += update_steps;
- if (verbose){
- view_percent (view, e, w);
- refresh ();
- }
- if (got_interrupt ())
- break;
- }
- disable_interrupt_key ();
- if (*d == get_byte (view, e))
- d++;
- else {
- e -= d - buffer;
- d = buffer;
- }
- enable_interrupt_key ();
- if (d - buffer == len){
- disable_interrupt_key ();
- return e - len;
- }
- }
- return 0;
- }
-
- /* States of our funny recognizer */
- enum {normal, inside_quotes, zero, hex1, hex2, oct1};
-
- /* This routine doesn't report all the user mistakes, it just ignores them */
- static void hex_search (WView *view, char *text)
- {
- char buffer [120]; /* Where we hold the information */
- int i, block_len;
- int v = 0;
- long pos; /* Where did we found the string */
- char *p; /* Temporary */
- int state = normal; /* Initial state of the micro-scanner */
-
- /* First convert the string to a stream of bytes */
- for (i = block_len = 0; text [i] && block_len < sizeof (buffer); i++){
- switch (state){
- case inside_quotes:
- if (text [i] == '"')
- state = normal;
- else
- buffer [block_len++] = text [i];
- break;
-
- case normal:
- if (text [i] == '"'){
- state = inside_quotes;
- break;
- }
- if (text [i] == '0'){
- state = zero;
- break;
- }
- if (text [i] == 'x'){
- state = hex1;
- break;
- }
- break;
-
- case zero:
- if (text [i] == 'x')
- state = hex1;
- break;
-
- case hex1:
- v = 0;
- text [i] = toupper (text [i]);
- if ((p = strchr (hex_char, text [i])) != 0){
- v = (p - hex_char) << 4;
- state = hex2;
- }
- break;
-
- case hex2:
- if ((p = strchr (hex_char, text [i])) != 0){
- v |= (p - hex_char);
- state = normal;
- }
- buffer [block_len++] = v;
- break;
- }
- }
- /* Then start the search */
- pos = block_search (view, buffer, block_len);
- if (!pos){
- message (0, " Search ", " Search string not found ");
- view->found_len = 0;
- return;
- }
-
- view->search_start = pos + 1;
- view->found_len = block_len;
-
- /* Adjust the file offset */
- view->start_display = (pos & (~(view->bytes_per_line-1)));
- if (view->start_display > get_bottom_first (view, 0, 0))
- view->start_display = view->bottom_first;
- }
-
- static int regexp_view_search (WView *view, char *pattern, char *string, int match_type)
- {
- static regex_t r;
- static char *old_pattern = NULL;
- static int old_type;
- int startpos, found_len, len;
-
- if (!old_pattern || strcmp (old_pattern, pattern) || old_type != match_type){
- if (old_pattern){
- regfree (&r);
- free (old_pattern);
- }
- if (regcomp (&r, pattern, REG_EXTENDED|REG_NOSUB)){
- message (1, " Error ", " Invalid regular expression ");
- return -1;
- }
- old_pattern = strdup (pattern);
- old_type = match_type;
- }
- len = strlen (string);
- startpos = re_search (&r, string, len, 0, len, NULL);
- if (startpos < 0)
- return 0;
- found_len = re_match (&r, string, len, startpos, NULL);
- view->found_len = found_len;
- view->search_start = startpos;
- return 1;
- }
-
- static void do_regexp_search (void *xview, char *regexp)
- {
- WView *view = (WView *) xview;
-
- view->search_exp = regexp;
- search (view, regexp, regexp_view_search);
- /* Had a refresh here */
- view->dirty++;
- view_update (view);
- }
-
- static void do_normal_search (void *xview, char *text)
- {
- WView *view = (WView *) xview;
-
- view->search_exp = text;
- if (view->hex_mode)
- hex_search (view, text);
- else
- search (view, text, icase_search_p);
- /* Had a refresh here */
- view->dirty++;
- view_update (view);
- }
-
- /* }}} */
- /* {{{ Mouse and keyboard handling */
-
- /* Real view only */
- static void help_cmd (void)
- {
- interactive_display (LIBDIR "mc.hlp", "[Internal File Viewer]");
- /*
- view_refresh (0);
- */
- }
-
- /* Both views */
- void toggle_wrap_mode (WView *view)
- {
- if (view->hex_mode){
- get_bottom_first (view, 1, 0);
- return;
- }
- wrap_mode = 1 - wrap_mode;
- get_bottom_first (view, 1, 0);
- if (wrap_mode)
- view->start_col = 0;
- else {
- if (have_fast_cpu){
- if (view->bottom_first < view->start_display)
- view->search_start = view->start_display = view->bottom_first;
- view->found_len = 0;
- }
- }
- view_labels (view);
- view->dirty++;
- view_update (view);
- }
-
- /* Both views */
- void toggle_hex_mode (WView *view)
- {
- view->hex_mode = 1 - view->hex_mode;
- altered_hex_mode = 1;
- get_bottom_first (view, 1, 0);
- view_labels (view);
- view->dirty++;
- view_update (view);
- }
-
- /* Both views */
- void goto_line (WView *view)
- {
- char *line, prompt [100];
- int i, oldline = 1;
-
- for (i = view->first; i < view->start_display; i++)
- if (get_byte (view, i) == '\n')
- oldline ++;
- sprintf (prompt, " The current line number is %d.\n"
- " Enter the new line number:", oldline);
- line = input_dialog (" Goto line ", prompt, "");
- if (line){
- if (*line){
- move_to_top (view);
- move_forward (view, atoi (line) - 1);
- }
- free (line);
- }
- view->dirty++;
- view_update (view);
- }
-
- /* Both views */
- void regexp_search (WView *view, int direction)
- {
- char *regexp = "";
- static char *old = 0;
-
- if (view->hex_mode)
- return;
-
- regexp = old ? old : regexp;
- regexp = input_dialog (" Search ", " Enter regexp:", regexp);
- if ((!regexp) || (!*regexp)){
- regexp = "";
- return;
- }
- if (old)
- free (old);
- old = strdup (regexp);
- #if 0
- /* Mhm, do we really need to load all the file in the core? */
- if (view->bytes_read < view->last_byte)
- get_byte (view, view->last_byte-1);/* Get the whole file in to memory */
- #endif
- view->direction = direction;
- do_regexp_search (view, regexp);
-
- view->last_search = do_regexp_search;
- }
-
- void regexp_search_cmd (WView *view)
- {
- regexp_search (view, 1);
- }
-
- /* Both views */
- void normal_search (WView *view, int direction)
- {
- static char *old;
- char *exp = "";
-
- exp = old ? old : exp;
- exp = input_dialog (" Search ", " Enter search string:", exp);
- if ((!exp) || (!*exp)){
- exp = "";
- return;
- }
- if (old)
- free (old);
- old = strdup (exp);
- /* FIXME: add this after 2.0: free (exp) */
-
- view->direction = direction;
- do_normal_search (view, exp);
- view->last_search = do_normal_search;
- }
-
- void normal_search_cmd (WView *view)
- {
- normal_search (view, 1);
- }
-
- void change_viewer (WView *view)
- {
- altered_magic_flag = 1;
- if (!view->command){
- view->viewer_magic_flag = !view->viewer_magic_flag;
- view_labels (view);
- } else {
- char *s = strdup (view->filename);
- char *t = strdup (view->command);
-
- view_done (view);
-
- /* Is it possible to not use the growing buffers? */
- if (!(*t && !*s))
- view->viewer_magic_flag = !view->viewer_magic_flag;
- view_init (view, t, s);
- free (s);
- free (t);
- view_labels (view);
- view->dirty++;
- view_update (view);
- }
- }
-
- static void change_nroff (WView *view)
- {
- view->viewer_nroff_flag = !view->viewer_nroff_flag;
- altered_nroff_flag = 1;
- view_labels (view);
- view->dirty++;
- view_update (view);
- }
-
- /* Real view only */
- static void quit_cmd (WView *view)
- {
- view->widget.parent->running = 0;
- }
-
- /* Both views */
- void view_labels (WView *view)
- {
- Dlg_head *h = view->widget.parent;
-
- define_label (h, (Widget *) view, 1, "Help", help_cmd);
-
- my_define (h, 10, "Quit", quit_cmd, view);
- my_define (h, 4, view->hex_mode ?"Ascii":"Hex", toggle_hex_mode, view);
- my_define (h, 5, "Line", goto_line, view);
- my_define (h, 6, view->hex_mode ? "" : "RxSrch", regexp_search_cmd, view);
-
- my_define (h, 2, view->hex_mode ? "" : wrap_mode ? "UnWrap" : "Wrap",
- toggle_wrap_mode, view);
-
- my_define (h, 7, view->hex_mode ? "HxSrch" : "Search",
- normal_search_cmd, view);
-
- my_define (h, 8, view->viewer_magic_flag ? "Raw" : "Parse",
- change_viewer, view);
-
- if (!view->have_frame){
- my_define (h, 9, view->viewer_nroff_flag ? "Unform" : "Format",
- change_nroff, view);
- my_define (h, 3, "Quit", quit_cmd, view);
- }
-
- redraw_labels (h, (Widget *) view);
- }
-
- /* Both views */
- static int check_left_right_keys (WView *view, int c)
- {
- if (c == KEY_LEFT)
- move_left (view);
- else if (c == KEY_RIGHT)
- move_right (view);
- else return 0;
-
- return 1;
- }
-
- enum { off, on };
-
- static void set_monitor (WView *view, int set_on)
- {
- int old = view->monitor;
-
- view->monitor = set_on;
-
- if (view->monitor){
- move_to_bottom (view);
- view->bottom_first = -1;
- set_idle_proc (view->widget.parent, 1);
- } else {
- if (old)
- set_idle_proc (view->widget.parent, 0);
- }
- }
-
- /* Both views */
- static int view_handle_key (WView *view, int c)
- {
- int prev_monitor = view->monitor;
-
- set_monitor (view, off);
-
- if (check_left_right_keys (view, c))
- return 1;
-
- if (check_movement_keys (c, 1, vheight, view, (movefn) move_backward, (movefn) move_forward, (movefn) move_to_top, (movefn) move_to_bottom)){
- return 1;
- }
-
- switch (c){
-
- case '?':
- regexp_search (view, -1);
- return 1;
-
- case '/':
- regexp_search (view, 1);
- return 1;
-
- /* Continue search */
- case XCTRL('s'):
- case 'n':
- if (view->last_search){
- (*view->last_search)(view, view->search_exp);
- } else {
- /* if not... then ask for an expression */
- normal_search (view, 1);
- }
- return 1;
-
- case XCTRL('r'):
- if (view->last_search){
- (*view->last_search)(view, view->search_exp);
- } else {
- normal_search (view, -1);
- }
- return 1;
-
- case 'h':
- move_left (view);
- return 1;
-
- case 'j':
- case '\n':
- case 'e':
- move_forward (view, 1);
- return 1;
-
- case 'd':
- move_forward (view, vheight / 2);
- return 1;
-
- case 'u':
- move_backward (view, vheight / 2);
- return 1;
-
- case 'k':
- case 'y':
- move_backward (view, 1);
- return 1;
-
- case 'l':
- move_right (view);
- return 1;
-
- case ' ':
- case 'f':
- move_forward (view, vheight - 1);
- return 1;
-
- case '!':
- exec_shell ();
- return 1;
-
- case 'F':
- set_monitor (view, on);
- return 1;
-
- case 'b':
- move_backward (view, vheight - 1);
- return 1;
-
- case KEY_IC:
- move_backward (view, 2);
- return 1;
-
- case KEY_DC:
- move_forward (view, 2);
- return 1;
-
- case 'm':
- view->marks [view->marker] = view->start_display;
- return 1;
-
- case 'r':
- view->start_display = view->marks [view->marker];
- view->dirty++;
- return 1;
-
- /* Use to indicate parent that we want to see the next/previous file */
- /* Only works on full screen mode */
- case XCTRL('f'):
- case XCTRL('b'):
- if (!view->have_frame)
- view->move_dir = c == XCTRL('f') ? 1 : -1;
- /* fall */
-
- case 'q':
- case XCTRL('g'):
- case ESC_CHAR:
- view->view_quit = 1;
- return 1;
-
- }
- if (c >= '0' && c <= '9')
- view->marker = c - '0';
-
- /* Restore the monitor status */
- set_monitor (view, prev_monitor);
-
- /* Key not used */
- return 0;
- }
-
- /* Both views */
- int view_event (WView *view, Gpm_Event *event, int *result)
- {
- *result = MOU_NORMAL;
- if (event->type & (GPM_DOWN|GPM_DRAG)){
- if (!wrap_mode){
- if (event->x < view->widget.cols / 4){
- move_left (view);
- *result = MOU_REPEAT;
- return 1;
- }
- if (event->x > 3 * vwidth / 4){
- move_right (view);
- *result = MOU_REPEAT;
- return 1;
- }
- }
- if (event->y < view->widget.lines / 3){
- if (mouse_move_pages_viewer)
- move_backward (view, view->widget.lines / 2 - 1);
- else
- move_backward (view, 1);
- *result = MOU_REPEAT;
- return 1;
- }
- else if (event->y > 2 * vheight /3){
- if (mouse_move_pages_viewer)
- move_forward (view, vheight / 2 - 1);
- else
- move_forward (view, 1);
- *result = MOU_REPEAT;
- return 1;
- }
- }
- return 0;
- }
-
- /* Real view only */
- int real_view_event (Gpm_Event *event, void *x)
- {
- int result;
-
- if (view_event ((WView *) x, event, &result))
- view_update ((WView *) x);
- return result;
- }
-
- /* }}} */
- /* {{{ Window creation, destruction and a driver stub for real view */
-
- static int view_mode_callback (struct Dlg_head *h, int id, int msg)
- {
- return default_dlg_callback (h, id, msg);
- }
-
- #ifdef HAVE_XVIEW
- /* Real view only */
-
- void view_adjust_size (Dlg_head *unused)
- {
- }
-
- int view (char *_command, char *_file, int *move_dir_p)
- {
- int midnight_colors [4];
- int error;
- WView *wview;
-
- wview = view_new (0, 0, COLS, LINES - 1, 0);
-
- error = view_init (wview, _command, _file);
- if (!error){
- x_view (wview);
- }
- *move_dir_p = 0;
- return !error;
- }
- #else
- Dlg_head *view_dlg;
-
- void view_adjust_size (Dlg_head *h)
- {
- WView *view;
- WButtonBar *bar;
-
- /* Look up the viewer and the buttonbar, we assume only two widgets here */
- view = (WView *) find_widget_type (h, (void *) &view_callback);
- bar = view->widget.parent->current->next->widget;
- widget_set_size (&view->widget, 0, 0, LINES-1, COLS);
- widget_set_size (&bar->widget, LINES-1, 0, 1, COLS);
- }
-
- /* Real view only */
- int view (char *_command, char *_file, int *move_dir_p)
- {
- int midnight_colors [4];
- int error;
- WView *wview;
- WButtonBar *bar;
-
-
- /* Create dialog and widgets, put them on the dialog */
- view_dlg = create_dlg (0, 0, LINES, COLS, midnight_colors,
- view_mode_callback, "[Internal File Viewer]",
- "view",
- DLG_NONE);
-
- wview = view_new (0, 0, COLS, LINES-1, 0);
-
- bar = buttonbar_new (1);
-
- add_widget (view_dlg, wview);
- add_widget (view_dlg, bar);
-
- error = view_init (wview, _command, _file);
- if (move_dir_p)
- *move_dir_p = 0;
-
- /* Please note that if you add another widget,
- * you have to modify view_adjust_size to
- * be aware of it
- */
- if (!error){
- run_dlg (view_dlg);
- if (move_dir_p)
- *move_dir_p = wview->move_dir;
- }
- destroy_dlg (view_dlg);
-
- return !error;
- }
- #endif
-
- static void view_hook (void *v)
- {
- WView *view = (WView *) v;
- WPanel *panel;
-
- /* If the user is busy typing, wait until he finishes to update the
- screen */
- if (!is_idle ()){
- if (!hook_present (idle_hook, view_hook))
- add_hook (&idle_hook, view_hook, v);
- return;
- }
-
- delete_hook (&idle_hook, view_hook);
-
- if (get_current_type () == view_listing)
- panel = current_panel;
- else if (get_other_type () == view_listing)
- panel = other_panel;
- else
- return;
-
- if (!S_ISREG (panel->dir.list [panel->selected].buf.st_mode))
- return;
-
- view_init (view, 0, panel->dir.list [panel->selected].fname);
- display (view);
- view_status (view);
- }
-
- static int view_callback (Dlg_head *h, WView *view, int msg, int par)
- {
- int v;
-
- switch (msg){
- case WIDGET_INIT:
- x_create_viewer (view);
- if (view->have_frame)
- add_hook (&select_file_hook, view_hook, view);
- else
- view_labels (view);
- break;
-
- case WIDGET_DRAW:
- display (view);
- view_status (view);
- break;
-
- case WIDGET_KEY:
- v = view_handle_key ((WView *)view, par);
- if (view->view_quit)
- h->running = 0;
- else {
- view_update (view);
- }
- return v;
-
- case WIDGET_IDLE:
- /* This event is generated when the user is using the 'F' flag */
- view->bottom_first = -1;
- move_to_bottom (view);
- display (view);
- view_status (view);
- sleep (1);
- return 1;
-
- case WIDGET_FOCUS:
- #ifdef HAVE_TK
- tk_evalf ("focus %s.v.view", wtk_win (view->widget));
- #endif
- view_labels (view);
- return 1;
-
- }
- return default_proc (h, msg, par);
- }
-
- WView *view_new (int y, int x, int cols, int lines, int is_panel)
- {
- WView *view = xmalloc (sizeof (WView), "view_new");
-
- init_widget (&view->widget, y, x, lines, cols,
- (callback_fn) view_callback,
- (destroy_fn) view_destroy,
- (mouse_h) real_view_event);
-
- view->filename = 0;
- view->view_active = 0;
- view->bottom_first = 0;
- view->start_col = 0;
- view->dirty = 0;
- view->hex_mode = default_hex_mode;
- view->viewer_magic_flag = default_magic_flag;
- view->viewer_nroff_flag = default_nroff_flag;
- view->view_quit = 0;
- view->move_dir = 0;
- view->have_frame = is_panel;
- view->last_byte = -1;
- view->monitor = 0;
- #ifdef HAVE_TK
- view->status_shown = 0;
- view->current_line = 1;
- view->cache_len = 80;
- view->last_col = 0;
- view->cache = xmalloc (81, "view->cache");
- view->color_cache = xmalloc (81, "view->cache");
- view->direction = 1;
- bzero (view->cache, 81);
- view->dest = 0;
- #endif
- widget_want_cursor (view->widget, 0);
-
- return view;
- }
-
- /* }}} */
- /* {{{ Emacs local variables */
-
- /*
- Cause emacs to enter folding mode for this file:
- Local variables:
- end:
- */
-
- /* }}} */
-